package cn.micro.keep.accounts.controller;

import cn.hutool.core.util.StrUtil;
import cn.micro.keep.accounts.api.Result;
import cn.micro.keep.accounts.auth.JwtTokenManager;
import cn.micro.keep.accounts.auth.LoginResult;
import cn.micro.keep.accounts.auth.MyAuthenticationProvider;
import cn.micro.keep.accounts.common.component.RedisService;
import cn.micro.keep.accounts.common.constant.SecurityConstants;
import cn.micro.keep.accounts.common.utils.RequestUtils;
import cn.micro.keep.accounts.entity.dto.LoginDTO;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
@Validated
@Slf4j
public class AuthController {

    private final MyAuthenticationProvider myAuthenticationProvider;

    private final JwtTokenManager jwtTokenManager;

    private final RedisService redisService;

    /**
     * token有效期(单位:秒)
     */
    @Value("${auth.token.ttl}")
    private Long tokenTtl;

    @PostMapping("login")
    public Object login(@RequestBody LoginDTO loginDTO){
        Authentication authenticate = myAuthenticationProvider.authenticate(loginDTO.getUsername(), loginDTO.getPassword(), loginDTO.getLoginType());
        //生成token
        String accessToken = jwtTokenManager.createToken(authenticate);
        LoginResult loginResult = LoginResult.builder()
                .tokenType(SecurityConstants.TOKEN_PREFIX)
                .accessToken(accessToken)
                .expires(tokenTtl)
                .build();
        return new Result<>().success(loginResult);
    }


    @DeleteMapping("/logout")
    public Object logout(HttpServletRequest request) {
        String token = RequestUtils.resolveToken(request);
        if (StrUtil.isNotBlank(token)) {
            Claims claims = jwtTokenManager.getTokenClaims(token);
            String jti = claims.get("jti", String.class);
            Date expiration = claims.getExpiration();
            if (expiration != null) {
                // 有过期时间，在token有效时间内存入黑名单，超出时间移除黑名单节省内存占用
                long ttl = (expiration.getTime() - System.currentTimeMillis());
                redisService.set(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + jti, null, ttl/1000);
            } else {
                // 无过期时间，永久加入黑名单
                redisService.set(SecurityConstants.BLACK_TOKEN_CACHE_PREFIX + jti, null);
            }
        }
        SecurityContextHolder.clearContext();
        return new Result<>().success("注销成功");
    }

    @PostMapping("sendSmsCaptcha")
    public Object sendSmsCaptcha(String phone){
        return new Result<>().success();
    }


}
